package com.pine.service.pineframework.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.pine.common.beans.exception.BusinessException;
import com.pine.common.beans.exception.ExceptionCodeEnum;
import com.pine.common.beans.pineframework.request.SysConfigQueryRequest;
import com.pine.common.beans.pineframework.response.SysConfigQueryResponse;
import com.pine.common.beans.request.PageRequest;
import com.pine.common.beans.response.PageResponse;
import com.pine.common.util.valid.ValidUtil;
import com.pine.dao.pineframework.entity.SysConfig;
import com.pine.manager.pineframework.SysConfigManager;
import com.pine.manager.pineframework.bo.SysConfigBo;
import com.pine.manager.pineframework.convertors.SysConfigConvertor;
import com.pine.manager.pineframework.dto.SysConfigImportDto;
import com.pine.manager.pineframework.query.SysConfigQuery;
import com.pine.service.pineframework.SysConfigService;
import com.pine.service.util.PageUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统配置表 服务实现类
 * </p>
 *
 * @author pine manage
 * @since 2024-08-12
 */
@Slf4j
@Service
public class SysConfigServiceImpl implements SysConfigService {

    @Resource
    private SysConfigManager sysConfigManager;

    @Resource
    private SysConfigConvertor sysConfigConvertor;

    private static final Map<String, SFunction<SysConfig, ?>> COLUMNS_FUNCTION_MAP;

    static {
        COLUMNS_FUNCTION_MAP = Map.of(
                "id", SysConfig::getId,
                "configKey", SysConfig::getConfigKey
        );
    }


    /**
     * 通过唯一key查询单个数据
     *
     * @param uniqueKey 唯一键
     * @param column    列名
     * @return 单个数据查询响应结果
     */
    @Override
    public SysConfigQueryResponse getOneByUniqueKey(Object uniqueKey, String column) {
        // 根据业务ID查询
        SysConfigBo sysConfigBo = sysConfigManager.getOneByUniqueKey(uniqueKey, COLUMNS_FUNCTION_MAP.getOrDefault(column, SysConfig::getId));
        return sysConfigConvertor.entityBoToQueryResponse(sysConfigBo);
    }

    /**
     * 查询信息（不分页）
     *
     * @param request 请求
     * @return 响应
     */
    @Override
    public List<SysConfigQueryResponse> list(SysConfigQueryRequest request) {
        SysConfigQuery sysConfigQuery = sysConfigConvertor.queryRequestToQuery(request);
        if (ObjectUtils.isNotEmpty(sysConfigQuery)) {
            List<SysConfigBo> sysConfigList = sysConfigManager.list(sysConfigQuery);
            if (ObjectUtils.isNotEmpty(sysConfigList)) {
                return sysConfigList.stream()
                        .map(sysConfigConvertor::entityBoToQueryResponse)
                        .filter(ObjectUtils::isNotEmpty)
                        .collect(Collectors.toList());
            }
        }
        return Collections.emptyList();
    }


    /**
     * 查询信息（分页）
     *
     * @param request 请求
     * @return PageResponse 响应
     */
    @Override
    public PageResponse<SysConfigQueryResponse> listPages(PageRequest<SysConfigQueryRequest> request) {
        try {
            // 分页查询
            IPage<SysConfigBo> sysConfigPage = sysConfigManager.page(transformToQuery(request));

            // 安全地处理分页转换逻辑
            return safelyConvertPage(sysConfigPage);
        } catch (Exception e) {
            log.error("查询失败", e);
            throw new BusinessException(ExceptionCodeEnum.SELECT_ERROR);
        }
    }


    /**
     * 安全地将分页数据转换为响应对象
     *
     * @param sysConfigPage 分页查询结果
     * @return 分页响应对象
     */
    private PageResponse<SysConfigQueryResponse> safelyConvertPage(IPage<SysConfigBo> sysConfigPage) {
        if (sysConfigPage == null || sysConfigPage.getRecords() == null) {
            return new PageResponse<>();
        }

        // 使用并行流进行转换以提高效率，但需确保线程安全
        List<SysConfigQueryResponse> responses = sysConfigPage.getRecords().parallelStream()
                .map(sysConfigBo -> sysConfigConvertor.entityBoToQueryResponse(sysConfigBo))
                .collect(Collectors.toList());

        return PageUtil.convertPage(sysConfigPage, responses);
    }


    /**
     * 将请求 request 转换成 manager 的 query 对象
     *
     * @param request 请求参数
     * @return query 对象
     */
    private PageRequest<SysConfigQuery> transformToQuery(PageRequest<SysConfigQueryRequest> request) {
        SysConfigQuery sysConfigQuery = sysConfigConvertor.queryRequestToQuery(request.getData());
        return new PageRequest<>(request.getPageNum(), request.getPageSize(), sysConfigQuery);
    }

    @Override
    public void syncExport(HttpServletResponse response, SysConfigQueryRequest request) {
        sysConfigManager.syncExport(response, sysConfigConvertor.queryRequestToQuery(request));
    }

    @Override
    public void getImportTemplate(HttpServletResponse response) {
        try {
            // 设置响应信息，文件名
            sysConfigManager.setResponseAndHeaderInfo(response, "系统配置_导入模版_");
            try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), SysConfigImportDto.class).autoCloseStream(false).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet("sheet").build();
                excelWriter.write(Collections.emptyList(), writeSheet);
            }
        } catch (Exception e) {
            log.warn("导出模版异常 {}", e.getLocalizedMessage(), e);
            throw new BusinessException(ExceptionCodeEnum.IMPORT_TEMPLATE_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importExcel(MultipartFile file) {
        try {
            // 默认每次会读取100条数据
            EasyExcel.read(file.getInputStream(), SysConfigImportDto.class, new PageReadListener<SysConfigImportDto>(importDtos -> {
                // 校验导入数据
                String validateResult = ValidUtil.validate(importDtos);
                if (StrUtil.isNotBlank(validateResult)) {
                    log.error("导入数据校验失败 {}", validateResult);
                    throw new BusinessException(String.valueOf(ExceptionCodeEnum.IMPORT_ERROR), validateResult);
                }

                // 数据转换
                List<SysConfigBo> sysConfigBos = sysConfigConvertor.importDtoToEntityBo(importDtos);
                // 保存到数据库
                sysConfigManager.saveBatch(sysConfigConvertor.entityBoToEntity(sysConfigBos));
            })).sheet().doRead();
        } catch (Exception e) {
            log.warn("上传文件异常 {}", e.getLocalizedMessage(), e);
            throw new BusinessException(ExceptionCodeEnum.IMPORT_ERROR);
        }
    }
}
